#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>

#include "graph.h"


PtrToNode createNode(uint id, float weight) {
	PtrToNode node = malloc(sizeof(struct Node));
	if (node == NULL) perror("out of space");
	node->id = id;
	node->weight = weight;
	node->next = NULL;
	node->inDegree = 0;
	return node;
}


PtrToGraph initGraph(int capacity) {
	PtrToGraph graph = malloc(sizeof(struct Graph));
	graph->capacity = capacity;
	graph->vertexNum = 0;
	graph->nodeList = malloc(sizeof(PtrToNode) * capacity);
	return graph;
}

PtrToNode find(PtrToGraph graph, uint id) {
	PtrToNode target;
	int i = 0;
	for (i = 0; i < graph->capacity; i++) {
		PtrToNode node = graph->nodeList[i];
		if (node != NULL && node->id == id) {
			target = node;
			break;
		}
	}
	return target;
}

void addNodeById(PtrToGraph graph, uint id) {
	if (graph->vertexNum == graph->capacity) {
		printf("graph full");
		return;
	}
	if (find(graph, id) != NULL) {
		printf("id %d exists\n", id);
		return;
	}

	int i = 0;
	PtrToNode node;
	for (i = 0; i < graph->capacity; i++) {
		node = graph->nodeList[i];
		if (node == NULL)break;
	}
	graph->nodeList[i] = createNode(id, 0.0f);
	graph->vertexNum ++;
}

void printAllNode(PtrToGraph graph) {
	PtrToNode node;
	int count = 0;
	int i = 0;
	for (i = 0; i < graph->capacity && count < graph->vertexNum; i++) {
		node = graph->nodeList[i];
		if (node != NULL) {
			count ++;
			// printf("%d\n", node->id);
			printAdjacent(node);
		} else {
			// printf("i=%d is NULL\n", i);
		}
	}
}

void printAdjacent(PtrToNode node) {
	while (node != NULL) {
		printf("id=%d, w=%.1f, in=%d  ", node->id, node->weight, node->inDegree);
		node = node->next;
	}
	printf("\n");
}

void addEdge(PtrToGraph graph, uint id1, uint id2, float weight) {
	// find the id1 node
	PtrToNode nodeId1 = find(graph, id1);
	if (nodeId1 == NULL) {
		printf("id %d not found", id1);
		return;
	}
	PtrToNode nodeId2 = find(graph, id2);
	if (nodeId2 == NULL) {
		printf("id %d not found", id2);
		return;
	}

	PtrToNode preNode = nodeId1;
	PtrToNode nextNode = nodeId1->next;
	while (nextNode != NULL) {
		if (nextNode->id == id2) {
			printf("(%d %d) already adjacent", id1, id2);
			return;
		}
		preNode = nextNode;
		nextNode = nextNode->next;
	}
	preNode->next = createNode(id2, weight);

	// nodeId2 inDegree++
	nodeId2->inDegree++;
}